package com.dflc.config;

import cn.dev33.satoken.stp.StpUtil;
import com.dflc.common.CommonConstant;
import com.dflc.entity.po.TLog;
import com.dflc.service.TLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;

@Aspect
@Component
public class LoggingAspect {

    @Resource
    private TLogService tLogService;

    /**
     * @Pointcut ：切入点声明，即切入到哪些目标方法。value 属性指定切入点表达式，默认为 ""。
     * 用于被下面的通知注解引用，这样通知注解只需要关联此切入点声明即可，无需再重复写切入点表达式
     * <p>
     * 切入点表达式常用格式举例如下：
     * - * com.wmx.aspect.EmpService.*(..))：表示 com.wmx.aspect.EmpService 类中的任意方法
     * - * com.wmx.aspect.*.*(..))：表示 com.wmx.aspect 包(不含子包)下任意类中的任意方法
     * - * com.wmx.aspect..*.*(..))：表示 com.wmx.aspect 包及其子包下任意类中的任意方法
     * </p>
     * value 的 execution 可以有多个，使用 || 隔开.
     */
    @Pointcut(value =
            "execution(* com.dflc.controller.BackManageController.SysUserInfoController.logout(..))" +
                    " || execution(* com.dflc.controller.BackManageController.SysUserInfoController.modifyPassword(..))" +
                    " || execution(* com.dflc.controller.BackManageController.SysUserInfoController.saveOrUpdateUserInfo(..))"+
                    " || execution(* com.dflc.controller.BackManageController.SysUserInfoController.deleteUserInfo(..))"+
                    " || execution(* com.dflc.controller.BackManageController.SysUserInfoController.resetPassword(..))"+
                    " || execution(* com.dflc.controller.BackManageController.SysUserInfoController.active(..))"+
                    " || execution(* com.dflc.controller.BackManageController.UnitController.addOrUpdateUnit(..))"   +
                    " || execution(* com.dflc.controller.DictionaryEntriesController.DictionaryEntriesController.addOrUpdateDictionaryEntries(..))"   +
                    " || execution(* com.dflc.controller.DictionaryEntriesController.DictionaryEntriesController.deleteDictionaryEntries(..))"   +
                    " || execution(* com.dflc.controller.SystemController.SysDataController.save(..))"   +
                    " || execution(* com.dflc.controller.SystemController.SysDataController.delete(..))"   +
                    " || execution(* com.dflc.controller.SystemController.SysMenuController.save(..))"   +
                    " || execution(* com.dflc.controller.SystemController.SysMenuController.delete(..))"   +
                    " || execution(* com.dflc.controller.SystemController.SysRoleController.save(..))"   +
                    " || execution(* com.dflc.controller.SystemController.SysRoleController.delete(..))"   +
                    " || execution(* com.dflc.controller.SystemController.SysRoleController.updateMenus(..))"   +
                    " || execution(* com.dflc.controller.BackManageController.UnitController.deleteUnit(..))")
    private void aspectPointcut() {

    }

    @Before(value = "aspectPointcut()")
    public void logBefore(JoinPoint joinPoint) {
        // 获取当前用户（这里假设有一个方法来获取用户名）
        Integer userId =  StpUtil.getLoginIdAsInt(); // 替换为实际获取用户名的逻辑

        // 获取方法签名和参数
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getName();
        String declaringTypeName = signature.getDeclaringTypeName();
        Object[] args = joinPoint.getArgs();

        // 创建日志记录对象
        TLog log = new TLog();
        log.setUserId(userId);
        log.setOperation(methodName);
        log.setType(CommonConstant.LogType.Req);
        log.setDescription(Arrays.toString(args)); // 简单地将参数转换为字符串
        log.setTimestamp(new Date());

        // 保存日志记录到数据库
        tLogService.save(log);
    }

    // 在目标方法成功执行并返回结果后记录日志
    @AfterReturning(pointcut = "aspectPointcut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {

        // 获取方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getName();
        if (methodName.equals("logout")) {
            return; // 如果是logout方法，则不记录日志
        }
        // 获取当前用户（替换为实际获取用户名的逻辑）
        Integer userId =  StpUtil.getLoginIdAsInt(); // 替换为实际获取用户名的逻辑

        // 创建日志记录对象
        TLog log = new TLog();
        log.setUserId(userId);
        log.setOperation(methodName);
        log.setType(CommonConstant.LogType.Rep);
        // 这里可以记录响应结果，但需要注意result的类型和如何序列化它
        // 如果response是一个复杂对象，你可能需要将其转换为JSON字符串或其他格式
        log.setDescription(result.toString()); // 简单地将结果转换为字符串，可能不够详细
        // 或者，如果你知道返回类型并且想要更详细的日志，可以这样做：
        // if (result instanceof SpecificResponseType) {
        //     SpecificResponseType specificResponse = (SpecificResponseType) result;
        //     log.setDescription(specificResponse.toDetailedString()); // 自定义的详细序列化方法
        // }
        log.setTimestamp(new Date());

        // 保存日志记录到数据库
        tLogService.saveOrUpdate(log);
    }
}